home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BCI NET
/
BCI NET Dec 94.iso
/
archives
/
applications
/
wp
/
ged11.lha
/
Install
/
data
/
main
/
GoldED
/
API
/
Dock
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-02
|
17KB
|
547 lines
/* -----------------------------------------------------------------------------
GoldED API client example code, ©1994 Dietmar Eilert. Dice:
dcc main.c -// -mRR -r -proto -2.0 -l tmsr.lib -l reqtoolssr.lib -o ram:dock
Note: Compiling this code requires ToolManger includes & ToolManager linker
libraries. ToolManager is ©1990-1994 Stefan Becker.
The following example uses synchronous ARexx communication: Requests are
PutMsg()'ed to GoldED's port, followed by a WaitPort() to get the editor's
response. This works fine since we need no ARexx communication after the API
link has been established. If there were ARexx communication AFTER the link has
been established (i.e. after sending the 'API PORT=...' command to register
with GoldED), we would have to use an asynchronous design beeing capable of
answering incoming API messages while waiting for completion of ARexx requests
sent to GoldED.
Note: La compilation de ce code demande les includes de ToolManager et les
bibliothèques de liaison ToolManager. ToolManager est ©1990-1994
Stefan Becker.
L'exemple suivant utilise les communications synchrones ARexx: les demandes
sont PutMsg()'ées au port de GoldED, suivies par un WaitPort() pour se procurer
la réponse de l'éditeur. Ceci fonctionne très bien comme nous n'avons pas
besoin de communications ARexx après l'établissement de la liaison API. S'il y
avait eu des communications ARexx APRES l'établissement de la liaison API
(après avoir envoyé la commande 'API PORT=...' pour s'enregistrer à GoldED),
nous aurions dû utiliser un système asynchrone étant capable de répondre aux
messages API arrivants pendant l'attente de la fin des demandes ARexx envoyées
à GoldED.
------------------------------------------------------------------------------
*/
/// "includes"
#define Prototype extern
#include <exec/exec.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <intuition/intuition.h>
#include <workbench/startup.h>
#include <rexx/errors.h>
#include <rexx/rxslib.h>
#include <libraries/reqtools.h>
#include <utility/tagitem.h>
#include <clib/toolmanager_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/rexxsyslib_protos.h>
#include <clib/reqtools_protos.h>
#include "golded:api/include/golded.h"
// ToolManager objects are a combination of action/image/sound:
// Les objets ToolManager sont une combinaison d'objets action/image/son:
struct tmTool {
APTR exec;
APTR icon;
APTR sound;
};
struct Library *ReqToolsBase;
Prototype void main(int, char **);
Prototype void HandleAPI(void *, char *, struct TagItem *, UWORD, UWORD);
Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *, char *);
Prototype char *xsprintf(char *, char *);
Prototype struct TagItem *ReadConfig(char *, void *, char *, UWORD *, UWORD *);
///
/// "main"
void
main(int argc, char **argv)
{
const char *version = "$VER: dock 1.4 (" __COMMODORE_DATE__ ")";
if ((argc == 2) || (argc == 3)) {
UBYTE *host, *prefs;
UWORD try;
void *handle;
prefs = (argc-- == 3) ? argv[1] : "progdir:dock.prefs";
// skip the "HOST=" part:
// sauter la partie "HOST=":
host = argv[argc] + 5;
// wait for ToolManager startup
// attendre le départ de ToolManager
for (try = 20; !(handle = AllocTMHandle()) && try; try--)
Delay(10);
if (handle) {
struct TagItem *dock;
UWORD dockX = ~0, dockY = ~0;
if (dock = ReadConfig(prefs, handle, host, &dockX, &dockY))
HandleAPI(handle, host, dock, dockX, dockY);
FreeTMHandle(handle);
}
else {
puts("got no TM handle ?!");
puts("pas de gestion TM ?!");
}
}
else {
puts("syntax error: dock [<config>] HOST=<host>");
puts("erreur de syntaxe: dock [<config>] HOST=<host>");
}
exit(0);
}
int
wbmain(struct WBStartup *startup)
{
if (ReqToolsBase = OpenLibrary("reqtools.library", 37)) {
rtEZRequestTags("No executable - to be used as API client", "OK", NULL, NULL, TAG_DONE);
CloseLibrary(ReqToolsBase);
}
}
///
/// "read config"
/* -------------------------------- ReadConfig ---------------------------------
Read config file. Return ready-to-use tag array for dock creation or NULL.
Write dock screen position to <dockX>/<dockY>.
Lire le fichier config. Retourne un tableau de tag prêt-à-être-utilisé pour
la création du dock ou NULL. Ecrit la position du dock en <dockX>/<dockY>.
*/
struct TagItem *
ReadConfig(prefs, handle, host, dockX, dockY)
void *handle;
char *prefs, *host;
UWORD *dockX, *dockY;
{
struct TagItem *dock = NULL;
BPTR config;
if (config = Open(prefs, MODE_OLDFILE)) {
struct RDArgs *rdArgs;
if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
static char buffer[256];
UWORD columns, entries, orientation;
columns = 1;
orientation = 0;
entries = 0;
while (FGets(config, buffer, 255)) {
char *cmd;
for (strcat(buffer, "\12"), cmd = buffer; *cmd && (*cmd != ';'); ++cmd) {
if ((*cmd != ' ') && (*cmd != 10)) {
ULONG n, argArray[] = { 0, 0, 0, 0, 0, 0 };
struct RDArgs *args;
static struct parser { char *command; char *template; } parser[] = {
"ADD", "COMMAND/K/A,AREXX/S,EXEC/S,DIR/K,OUTPUT/K,ICON/K/A",
"DOCK", "X/N,Y/N,HORIZONTAL/S,COLUMNS/N",
NULL
};
for (n = 0; parser[n].command; ++n) {
if (!memcmp(cmd, parser[n].command, strlen(parser[n].command))) {
cmd += strlen(parser[n].command);
rdArgs->RDA_Source.CS_Buffer = cmd;
rdArgs->RDA_Source.CS_Length = strlen(cmd);
rdArgs->RDA_Source.CS_CurChr = 0;
rdArgs->RDA_DAList = NULL;
rdArgs->RDA_Buffer = NULL;
if (args = ReadArgs(parser[n].template, argArray, rdArgs)) {
if (n == 0) {
char execName[8], iconName[8];
struct TagItem iconTags[] = { TMOP_File, strdup((char *)argArray[5]), TMOP_Data, NULL, TAG_DONE };
struct TagItem execTags[] = {
TMOP_Command, xsprintf((char *)argArray[0], host),
TMOP_ExecType, argArray[1] ? TMET_ARexx : TMET_CLI,
TMOP_Stack, 8192,
TMOP_CurrentDir, argArray[3] ? strdup((char *)argArray[3]) : NULL,
TMOP_Output, argArray[4] ? strdup((char *)argArray[4]) : NULL,
TAG_DONE
};
sprintf(execName, "e%ld", entries);
sprintf(iconName, "i%ld", entries++);
CreateTMObjectTagList(handle, strdup(execName), TMOBJTYPE_EXEC, execTags);
CreateTMObjectTagList(handle, strdup(iconName), TMOBJTYPE_IMAGE, iconTags);
}
else if (n == 1) {
if (argArray[0])
*dockX = *(ULONG *)argArray[0];
if (argArray[1])
*dockY = *(ULONG *)argArray[1];
if (argArray[2])
orientation = 1;
if (argArray[3])
columns = *(ULONG *)argArray[3];
}
FreeArgs(args);
}
}
}
break;
}
}
if (entries) {
if (dock = (struct TagItem *)calloc((entries + 9) * sizeof(struct TagItem), 1)) {
UWORD n;
dock[0].ti_Tag = TMOP_PubScreen;
dock[1].ti_Tag = TMOP_LeftEdge;
dock[2].ti_Tag = TMOP_TopEdge;
dock[3].ti_Tag = TMOP_Activated;
dock[4].ti_Tag = TMOP_Centered;
dock[5].ti_Tag = TMOP_Columns;
dock[6].ti_Tag = TMOP_Vertical;
dock[7].ti_Tag = TMOP_Text;
dock[8].ti_Tag = TAG_DONE;
dock[3].ti_Data = TRUE;
dock[5].ti_Data = columns;
dock[6].ti_Data = orientation;
for (n = 0; n < entries; ++n) {
struct tmTool *tool;
if (tool = (struct tmTool *)calloc(sizeof(struct tmTool), 1)) {
if ((tool->exec = calloc(8, 1)) && (tool->icon = calloc(8, 1))) {
sprintf((char *)tool->exec, "e%ld", n);
sprintf((char *)tool->icon, "i%ld", n);
dock[8 + n].ti_Tag = TMOP_Tool;
dock[8 + n].ti_Data = tool;
}
}
}
}
}
}
FreeDosObject(DOS_RDARGS, rdArgs);
}
Close(config);
}
else {
puts("dock.prefs missing");
puts("dock.prefs manquant");
}
return(dock);
}
///
/// "API management"
/* --------------------------------- HandleAPI ---------------------------------
Register with GoldED & handle incoming API messages.
*/
void
HandleAPI(handle, host, dock, dockX, dockY)
struct TagItem *dock;
char *host;
void *handle;
UWORD dockX, dockY;
{
struct MsgPort *replyPort;
if (replyPort = CreateMsgPort()) {
char command[255];
ULONG *result;
sprintf(command, "API PORT=%ld MASK=%ld", replyPort, API_CLASS_ROOT | API_CLASS_SCREEN);
if (result = SendRexxCommand(host, command, replyPort, NULL)) {
if (*result == RC_OK) {
BOOL active = TRUE;
do {
struct APIMessage *apiMsg, *nextMsg;
// API messages might already have arrived since SendRexxCommand() only pulls one message of the port
while (!(apiMsg = (struct APIMessage *)GetMsg(replyPort)))
WaitPort(replyPort);
do {
for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
if (nextMsg->api_State == API_STATE_NOTIFY) {
switch (nextMsg->api_Class) {
case API_CLASS_ROOT:
switch (nextMsg->api_Action) {
case API_ACTION_DIE:
active = FALSE;
DeleteTMObject(handle, "dock1");
break;
case API_ACTION_INTRODUCE:
static struct TagItem tags[] = {
API_Client_Name, "dock",
API_Client_Copyright, "©1994 Dietmar Eilert",
API_Client_Purpose, "ToolManager dock for GoldED",
TAG_DONE
};
nextMsg->api_Data = tags;
break;
default:
nextMsg->api_Error = API_ERROR_UNKNOWN;
}
break;
case API_CLASS_SCREEN:
switch (nextMsg->api_Action) {
case API_ACTION_HIDE:
DeleteTMObject(handle, "dock1");
break;
case API_ACTION_SHOW:
struct Screen *screen;
if (screen = LockPubScreen(nextMsg->api_Screen)) {
dock[0].ti_Data = nextMsg->api_Screen;
dock[1].ti_Data = (dockX == ~0) ? screen->Width : dockX;
dock[2].ti_Data = (dockY == ~0) ? screen->BarHeight + ((screen->BitMap.Depth == 1) ? 2 : 1) : dockY;
UnlockPubScreen(NULL, screen);
}
CreateTMObjectTagList(handle, "dock1", TMOBJTYPE_DOCK, dock);
break;
default:
nextMsg->api_Error = API_ERROR_UNKNOWN;
}
break;
default:
nextMsg->api_Error = API_ERROR_UNKNOWN;
}
}
}
ReplyMsg((struct Message *)apiMsg);
} while (apiMsg = (struct APIMessage *)GetMsg(replyPort));
} while (active);
}
}
DeleteMsgPort(replyPort);
}
}
///
/// "misc"
/* --------------------------------- xsprintf ----------------------------------
sprintf frontend (malloc buffer); limited to string insertion into string
façade sprintf (malloc tampon); limité à l'insertion de chaînes dans la chaîne
*/
char *
xsprintf(mask, var)
char *mask, *var;
{
char *buffer;
if (buffer = malloc(strlen(mask) + strlen(var)))
sprintf(buffer, mask, var);
return(buffer);
}
///
/// "ARexx"
/* ---------------------------------- SendRexxCommand -------------------------
Send ARexx message & wait for answer. Return pointer to result or NULL.
Envoie un message ARexx & attend une réponse. Retourne un pointeur comme résul-
tat ou NULL.
*/
ULONG *
SendRexxCommand(port, cmd, replyPort, buffer)
char *cmd, *port, *buffer;
struct MsgPort *replyPort;
{
struct MsgPort *rexxport;
Forbid();
if (rexxport = FindPort(port)) {
struct RexxMsg *rexxMsg, *answer;
if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
static ULONG result;
rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
PutMsg(rexxport, &rexxMsg->rm_Node);
do {
WaitPort(replyPort);
if (answer = (struct RexxMsg *)GetMsg(replyPort))
result = answer->rm_Result1;
} while (!answer);
Permit();
if (answer->rm_Result1 == RC_OK) {
if (answer->rm_Result2) {
if (buffer)
strcpy(buffer, (char *)answer->rm_Result2);
DeleteArgstring((char *)answer->rm_Result2);
}
}
DeleteArgstring((char *)ARG0(answer));
DeleteRexxMsg(answer);
return(&result);
}
}
}
Permit();
return(NULL);
}
///